#include <iostream>
#include <cstring>
#include <string>
#include "nocopy.hpp" //禁止拷贝
#include "Log.hpp"
// OS
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

//./client serverip serverport
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        std::cout << "Usage: ./xxx serverip serverport" << std::endl;
        exit(-1);
    }
    std::string ser_ip = argv[1];
    uint16_t ser_port = std::stoi(argv[2]);

    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        Log(FATAL, "socket fail");
        exit(-1);
    }
    // OS会自动填充+bind
    // 填充目标server_socket
    struct sockaddr_in server_socket;
    uint len = sizeof(server_socket);
    bzero(&server_socket, len);         // 初始化
    server_socket.sin_family = AF_INET; // ipv4网络地址族
    server_socket.sin_port = htons(ser_port);
    // server_socket.sin_addr.s_addr =  //随便发
    // server_socket.sin_zero
    while (1)
    {
        // 读取键盘 + 发送
        std::string str;
        std::getline(std::cin, str);
        int n = sendto(sockfd, str.c_str(), str.size(), 0, (struct sockaddr *)&server_socket, len);
        if (n >= 0)
        {
            // 接收
            sockaddr_in ser_socket; // 虽然不用，但可以用来占位防止出错，比nullptr好
            uint len = sizeof(ser_socket);
            std::string buff_str;
            buff_str.resize(1024); // 扩容
            int re = recvfrom(sockfd, &buff_str[0], buff_str.size(), 0, (struct sockaddr *)&ser_socket, &len);
            // recvfrom(sockfd, (void*)buff_str.data(), buff_str.size(), 0, (struct sockaddr*)&ser_socket, &len);
            if (re >= 0)
            {
                Log(INFO, "recvfrom success");
                buff_str[re] = '\0'; // 末尾加0
                std::cout << "server return sendto:" << buff_str << std::endl;
            }
            else
            {
                Log(FATAL, "recvfrom fail");
                break;
            }
        }
        else //(n < 0) // 比//n == -1 增加了健壮性/鲁棒性
        {
            Log(FATAL, "sendto fail");
            // exit(-1);
            break;
        }
    }

    close(sockfd);

    return 0;
}